#ifndef __SCREEN_MIRROR_STREAM_H__
#define __SCREEN_MIRROR_STREAM_H__

#include <map>
#include <mutex>
#include <string>
#include <functional>
#include "Pal/VideoDec.h"
#include "Pal/AudioIn.h"
// #include "Parser/Frame.h"
#include "json.h"
// #include "Config.h"
#include "customdisplay/UsbDisplayReceiver.h"
#include "airplay/AirplayReceiver.h"
#include "StreamComposeMgr.h"
#include "Poller/Timer.h"
#include "mediaPriv.h"
#include "Thread/Thread.h"
#include <queue>



namespace Media{

class VideoDecode;
class AudioEncode;
class VideoEncode;
class AudioInMgr;


typedef enum MirrorStreamType
{
    PRIVATE,    
    AIRPLAY,   
    MIRACAST,
}MirrorStreamType;

class ScreenMirrorStream{

public:

	const uint16_t QueueSize = 90;
    static const uint8_t  QueueArray = 2;
    //视频数据集
    struct FrameBuffer 
	{
	    uint64_t timestamp; /*< timestamp*/
		size_t size; /*< data length*/
		uint8_t* data; /*< raw data*/

		FrameBuffer(size_t len)
		: timestamp(0)
		, size(len)
		, data(NULL)
		{
			data = new uint8_t[len];
		}

		~FrameBuffer()
		{
			delete []data;
			data = NULL;
		}

		FrameBuffer(const FrameBuffer&);
		FrameBuffer& operator=(const FrameBuffer&);
	};

    // 定义智能指针
    typedef std::shared_ptr<FrameBuffer> FramePtr;

public:

	static ScreenMirrorStream *instance();

	bool stop();

	bool start(StreamPlayInfo playInfo);

	bool streamInit();

	bool setFormat(const Json::Value &table);

	void setActivateSecret(std::string secret);

	bool setVideoPacket(const unsigned char *buffer, int buflen, uint64_t timestamp);

	bool setStreamDisplayChn(int channel);

	bool sendAudioPacket(const unsigned char *buffer, int buflen, uint64_t timestamp);

	StreamAbility getPlayAbility();

	UsbDisplayContext* getContext();

	bool getMirrorCode(std::string&        pinCode);

	bool outputStart();
	
	bool outputStop();

    bool VideoGetPacket(SCREEN_vencPacket_t *pPacket);

    bool VideoReleasePacket();

    bool AudioGetPacket(char *buf, int *length, uint64_t& pts);

    bool startSwitchTimer(bool state);

    bool mirrorAVStart();

    bool mirrorAVStop();

    bool dymicSwitchCurtain(bool state);

    bool saveToCommQueue(const unsigned char *buffer, int buflen, uint64_t timestamp, uint8_t index);

    bool setVideoDecFormat(VideoDecFormat *format);

    bool HdmioutControl(uint8_t cmd);

    bool setShareScreenStatus(bool state);

    bool getShareScreenStatus();

    bool clearCommQueue();

    bool streamComeDel(int clientType, const char *ip);

    bool streamLeaveDel();

	bool setServerName(std::string name);

	bool updateServerPassword();

	bool getAirplayConnect();

	bool getUsbDisplayConnect();

	std::string getdevicePassword();

	bool setdevicePassword(std::string pwd);
	
	std::string getdeviceServerName();

	bool setdeviceServerName(std::string serverName);

	bool setAirplayConnect(bool status);

	bool setUsbDisplayConnect(bool status);
	
	bool isActived();

	void setActiveCode(const char *code);

	void setAudioFormat(AudioInAttr format);
private:
	ScreenMirrorStream();

	bool setStreamType(std::string type);

	bool streamStart();
	
	bool streamStop(void);

	bool getDeviceMac(void);

	bool usbDisplayInit(void);

	void initUsbDisplayCallback(void);

	bool airplayStart(void);

	bool airplayInit(void);

	bool airplayStop(void);

	bool usbDisplayStart(void);

	bool usbDisplayStop(void);

	bool usbDisplaySetFormat(const Json::Value &table);

	bool MirrorCodeRefresh();

    bool getCommQueueMsg(FramePtr& msg, uint8_t index);

    void StreamInProc(Fdt::Thread *thread);

    void StreamInAudioProc(Fdt::Thread *thread);

	int generateRandomFourDigitNumber();




private:
	static ScreenMirrorStream *         	sm_mirrorSteramIns;

	static std::mutex 			            sm_insMutex;

	bool                                    m_hasInited;

	UsbDisplayContext*                      m_usbDisplayContext = nullptr;
	
    UsbDisplayParameter                     m_usbDisplayParameter;

    airplay_parameter_t                     m_airplayParameter;

    airplay_callbacks_t                     m_airplayCallFun;

    MirrorStreamType                        m_curStreamType;

    char                                    m_macAddrStr[32];

    std::string                             m_activeCode;

    std::string                             m_activateSecret;

	std::string								m_deviceServerName;

    std::string                             m_devicePassword;

	std::mutex								m_pwdLock;

	bool 									m_airplayConnect = false;

	bool 									m_usbdisplayConnect = false;

	std::mutex								m_usbConnectLock;
	
	std::mutex								m_airplayConnectLock;

	
	std::mutex								m_UserPwdLock;

    VideoDecode*                            m_pVideoDecode = nullptr;
	
	int 									m_videoChannel = -1;
	
	bool									m_started; //start作为启动标志,避免多个业务多次启停

	VideoDecPacket                          m_videoPacket;

	std::mutex 			                    m_paramMutex;

	TaskInfo                                m_taskInfo = {0};

	std::shared_ptr<Fdt::Timer>             m_taskTimer;

	int 									m_audioChannel = -1;

	AudioInPacket                           m_audioPacket; 

	AudioInMgr*                             m_pAudioInput = nullptr;

	StreamAbility                           m_playAbility;

	VideoEncode*							m_pVideoEncode = nullptr;

	AudioEncode*                            m_pAudioEncode = nullptr;

	std::string                             m_pinCode = "";

	std::shared_ptr<Fdt::Timer>             m_codeTimer;

	bool                                    m_codeTimerStatus = false;

	std::mutex 			                    m_codeMutex;

	std::shared_ptr<Fdt::Timer>             m_switchTimer;

	std::mutex 			                    m_switchMutex;

	std::mutex                              m_queueMutex[QueueArray];
	
    std::queue<FramePtr>                    m_frameaQueue[QueueArray];

    FramePtr                                m_framePtr;

    bool                                    m_shareScreenState = false;

    Fdt::Thread 						    m_streamInThread{"ScreenMirrorStreamSave"};//thread放在最后,保证thread最后构造,最先析构

    Fdt::Thread 						    m_streamAudioThread{"ScreenMirrorStreamAudio"};//thread放在最后,保证thread最后构造,最先析构


/*
	std::string								_configName{"Encode.Video.Chn"};
	Json::Value								_config;
	//start作为启动标志,避免多个业务多次启停
	bool									_started = false;
	//_run作为运行标志,某些使能情况下不能去获取帧,例如设置格式重更新启停的时候
	VideoDecFormat							_format;
	bool									_setting = false;
	ScreenMirrorStreamr *							_videoEncoder = nullptr;
	int 									_channel = 0;
	std::recursive_mutex 					_mutex;
	std::map<void *, std::shared_ptr<CallBack>> 	_func_map;
	Fdt::Thread 						_thread{"Video0"};//thread放在最后,保证thread最后构造,最先析构
*/
};

}//namespace Media
#endif


